package com.xsystem.api.util;

import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

import net.sf.json.JSONObject;
import net.sf.json.xml.XMLSerializer;

public final class ApiResponseUtil {

	private static final String DEFAULT_ENCODING = "UTF-8";

	private ApiResponseUtil() {
	}

	public static String prepareResponseNameValuePair(Map<String, Object> responseMap) {
		StringBuilder content = new StringBuilder();
		try {
			for (Entry<String, Object> entry : responseMap.entrySet()) {
				String key = entry.getKey();
				Object valueObj = entry.getValue();

				if (valueObj instanceof Collection<?>) {
					int i = 0;
					for (Object o : (Collection<?>) valueObj) {
						if (o instanceof Map<?, ?>) {
							for (Entry<?, ?> e : ((Map<?, ?>) o).entrySet()) {
								String eKey = (String) e.getKey();
								String eValue = (String) e.getValue();

								String keyFirstLetter = eKey.substring(0, 1).toUpperCase();
								eKey = keyFirstLetter + eKey.substring(1, eKey.length());

								content.append(key + eKey + "_i" + i + "="
										+ URLEncoder.encode(eValue, DEFAULT_ENCODING) + "&");
							}
						} else {
							content.append(key + "_i" + i + "="
									+ URLEncoder.encode(String.valueOf(o), DEFAULT_ENCODING) + "&");
						}
						i++;
					}
				} else if (valueObj instanceof Map<?, ?>) {
					@SuppressWarnings("unchecked")
					HashMap<String, Object> valueObjMap = (HashMap<String, Object>) valueObj;
					content.append(key + ":");
					for (Entry<String, Object> vEntry : valueObjMap.entrySet()) {
						String vKey = vEntry.getKey();
						Object vValue = vEntry.getValue();
						if (!(vValue instanceof String)) {
							vValue = vValue + "";
						}
						String vValueStr = String.valueOf(vValue);
						content.append(vKey + "=" + URLEncoder.encode(vValueStr, DEFAULT_ENCODING) + "&");
					}
				} else {
					String value = String.valueOf(valueObj);
					content.append(key + "=" + URLEncoder.encode(value, DEFAULT_ENCODING) + "&");
				}
			}
		} catch (UnsupportedEncodingException e) {
			e.printStackTrace();
		}

		String contentString = content.toString();
		if (contentString.length() > 0) {
			contentString = contentString.substring(0, contentString.length() - 1);
		}
		return contentString;
	}

	public static String prepareResponseJson(Map<String, Object> hm) {
		JSONObject json = JSONObject.fromObject(hm);
		return json.toString();
	}

	public static String prepareJson(Map<String, String> hm) {
		JSONObject json = JSONObject.fromObject(hm);
		return json.toString();
	}

	public static String prepareResponseXml(Map<String, Object> hm) {
		XMLSerializer xml = new XMLSerializer();
		JSONObject json = JSONObject.fromObject(hm);
		return xml.write(json);
	}

	// Get NVP from a base list (Can be nested)
	// E.g. "0=aaa&1=bbb&2=ccc"
	private static String toNvp(List<?> list) throws UnsupportedEncodingException {

		StringBuilder content = new StringBuilder();
		int index = 0;

		for (Object valueObj : list) {

			String key = Integer.toString(index);
			String value = null;

			if (valueObj == null) {
				value = "";
			} else if (valueObj instanceof List<?>) {
				value = toNvp((List<?>) valueObj); // recursive
			} else if (valueObj instanceof Map<?, ?>) {
				value = toNvp((Map<?, ?>) valueObj); // recursive
			} else {
				value = valueObj.toString();
			}

			if (index > 0) {
				content.append('&');
			}
			content.append(key + "=" + URLEncoder.encode(value, DEFAULT_ENCODING));
			index++;
		}
		return content.toString();
	}

	// Get NVP from a base map (Can be nested)
	// E.g. "key1=value1&key2=value2&key3=value3"
	private static String toNvp(Map<?, ?> map) throws UnsupportedEncodingException {

		StringBuilder content = new StringBuilder();
		boolean isFirst = true;

		for (Entry<?, ?> entry : map.entrySet()) {

			String key = entry.getKey().toString();
			Object valueObj = entry.getValue();
			String value = null;

			if (valueObj == null) {
				value = "";
			} else if (valueObj instanceof List<?>) {
				value = toNvp((List<?>) valueObj); // recursive
			} else if (valueObj instanceof Map<?, ?>) {
				value = toNvp((Map<?, ?>) valueObj); // recursive
			} else {
				value = valueObj.toString();
			}

			if (isFirst) {
				isFirst = false;
			} else {
				content.append('&');
			}

			content.append(key + "=" + URLEncoder.encode(value, DEFAULT_ENCODING));
		}
		return content.toString();
	}

}
